#include "N1MLTDataStorage.h"
#include "N1Debug.h"

static char*   gDataArray;
static uint32  gDataSize;
static uint32  gSlotSize;
static uint32  gMaxElementsCount;
static uint32  gFirstFreeElement;


static uint32 _N1MltFindEmptySlot()
{
    for(uint32 i=0;i<gFirstFreeElement;i++)
    {
        if(*(int*)(gDataArray + i * gSlotSize) == 0)
        {
            return i;
        }
    }
    N1Assert(gFirstFreeElement<gMaxElementsCount);

    return gFirstFreeElement++;
}


static int32 _N1MltFindSlotByKey(const void* key)
{
    for(uint32 i=0;i<gFirstFreeElement;i++)
    {
        if(*(int*)(gDataArray + i * gSlotSize) == (int)key)
        {
            return i;
        }
    }
    return -1;
}

void N1MltAddObject(const void* key, const void* data)
{
    uint32 slot = _N1MltFindEmptySlot();
    *(int*)(gDataArray + slot * gSlotSize) = (int)key;
    memcpy( (gDataArray + slot * gSlotSize + sizeof(void*)), data, gDataSize);
}

void* N1MltFindObject(const void* key)
{
    int32 slot = _N1MltFindSlotByKey(key);
    if(slot>=0)
    {
        return (gDataArray + slot * gSlotSize + sizeof(void*));
    } 
    return NULL;
}

void N1MltRemoveObject(const void* key)
{
    int32 slot = _N1MltFindSlotByKey(key);
    if(slot>=0)
    {
        *(int*)(gDataArray + slot * gSlotSize) = 0;
    } 
    else
    {
        N1Assert(0);
    }
}

bool N1MltGetFirstObject(N1MltDataStorageIterator &it)
{
    for(uint32 i=0;i<gFirstFreeElement;i++)
    {
        if(*(int*)(gDataArray + i * gSlotSize) != 0)
        {
            it = i;
            return true;
        }
    }
    return false;
}

bool N1MltGetNextObject(N1MltDataStorageIterator &it)
{
    for(uint32 i=it+1;i<gFirstFreeElement;i++)
    {
        if(*(int*)(gDataArray + i * gSlotSize) != 0)
        {
            it = i;
            return true;
        }
    }
    return false;
}

const void* N1MltGetObject(N1MltDataStorageIterator it)
{
    return gDataArray + it * gSlotSize + sizeof(void*);
}

void N1MltDataStorageInitialize(uint32 elementSize, uint32 maxElementCount)
{
    gDataSize = elementSize;
    gSlotSize = elementSize + sizeof(void*);
    gDataArray = (char*)malloc( gSlotSize * maxElementCount);
    gMaxElementsCount = maxElementCount;
    gFirstFreeElement = 0;
}

void N1MltDataStorageUninitialize()
{
    free(gDataArray);
    gMaxElementsCount = 0;
    gFirstFreeElement = 0;
    gDataSize = gSlotSize = 0;
}
